#include <hw/inout.h>
#include <sys/neutrino.h>
#include <stdint.h>
#include "AD.h"
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>

uintptr_t ad_lsbHandle;
uintptr_t ad_msbHandle;
uintptr_t adChannelHandle;
uintptr_t ad_analogInputStatusHandle;

void initADRegister(void)
{
	// Get a handle to the LSB of the A/D register
	ad_lsbHandle = mmap_device_io( 1, AD_LSB_BASE_ADDRESS );
	if(ad_lsbHandle==MAP_DEVICE_FAILED ) {
		printf("A");
	}
	// Get a handle to the MSB of the A/D register
	ad_msbHandle = mmap_device_io( 1, AD_MSB_BASE_ADDRESS );
	if(ad_msbHandle==MAP_DEVICE_FAILED ) {
		printf("B");
	}

	// Get a handle to the A/D channel register
	adChannelHandle = mmap_device_io( 1, AD_CHANNEL_ADDRESS );
	if(adChannelHandle==MAP_DEVICE_FAILED ) {
		printf("C");
	}
	// Set the board to only use channel 4
	out8( adChannelHandle, AD_CHANNEL_VAL );

	// Get a handle to the analog input status register
	ad_analogInputStatusHandle = mmap_device_io( 1, ANALOG_INPUT_STATUS_ADDRESS );
	if(ad_analogInputStatusHandle==MAP_DEVICE_FAILED ) {
		printf("C");
	}
	// Select the input range for the A/D converter
	out8( ad_analogInputStatusHandle, ANALOG_INPUT_STATUS_VAL );	// +10V, -10V range, no scan
}

float readValue() {
	uint8_t lsbData;
	uint8_t msbData;
	int16_t combined;
	//Wait for A/D to be ready
	while ( ( in8( ad_analogInputStatusHandle ) & ANALOG_INPUT_WAIT_BIT ) != 0 )
	{
		usleep(AD_WAIT);
	}

	//Start conversion
	out8( ad_lsbHandle, 0b00010000);
	out8( ad_lsbHandle, AD_BASE_OUTPUT_VAL );

	//Wait for result to be ready
	while ( ( in8( ad_analogInputStatusHandle ) & AD_BASE_OUTPUT_VAL ) != 0 )
	{
		usleep(AD_WAIT);
	}

	lsbData = in8( ad_lsbHandle );
	msbData = in8( ad_msbHandle );
	combined = ( msbData << 8 ) + lsbData;

	return (((float)combined)/32768)*10;
}
